﻿Imports Microsoft.CSharp
Imports Microsoft.VisualBasic
Imports System
Imports System.CodeDom.Compiler
Imports System.Collections
Imports System.Collections.Specialized
Imports System.ComponentModel.Design
Imports System.Globalization
Imports System.Reflection
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class IdentifierCreationService
        Implements IIdentifierCreationService
        ' Methods
        Friend Sub New(ByVal serviceProvider As IServiceProvider, ByVal loader As WorkflowDesignerLoader)
            Me.serviceProvider = serviceProvider
            Me.loader = loader
        End Sub

        Private Function GetRootActivityType(ByVal serviceProvider As IServiceProvider) As Type
            Dim service As IDesignerHost = [TryCast](serviceProvider.GetService(GetType(IDesignerHost)),IDesignerHost)
            If (service Is Nothing) Then
                Throw New Exception(SR.GetString("General_MissingService", New Object() { GetType(IDesignerHost).FullName }))
            End If
            Dim rootComponentClassName As String = service.RootComponentClassName
            If String.IsNullOrEmpty(rootComponentClassName) Then
                Return Nothing
            End If
            Dim provider As ITypeProvider = [TryCast](serviceProvider.GetService(GetType(ITypeProvider)),ITypeProvider)
            If (provider Is Nothing) Then
                Throw New Exception(SR.GetString("General_MissingService", New Object() { GetType(ITypeProvider).FullName }))
            End If
            Return provider.GetType(rootComponentClassName, False)
        End Function

        Private Shared Function IsPreBuiltActivity(ByVal activity As Activity) As Boolean
            Dim activity2 As CompositeActivity = activity.Parent
            Do While (Not activity2 Is Nothing)
                If Helpers.IsCustomActivity(activity2) Then
                    Return True
                End If
                activity2 = activity2.Parent
            Loop
            Return False
        End Function

        Private Sub System.Workflow.ComponentModel.Design.IIdentifierCreationService.EnsureUniqueIdentifiers(ByVal parentActivity As CompositeActivity, ByVal childActivities As ICollection) Implements IIdentifierCreationService.EnsureUniqueIdentifiers
            If (parentActivity Is Nothing) Then
                Throw New ArgumentNullException("parentActivity")
            End If
            If (childActivities Is Nothing) Then
                Throw New ArgumentNullException("childActivities")
            End If
            Dim list As New ArrayList
            Dim queue As New Queue(childActivities)
            Do While (queue.Count > 0)
                Dim activity As Activity = DirectCast(queue.Dequeue, Activity)
                If TypeOf activity Is CompositeActivity Then
                    Dim activity2 As Activity
                    For Each activity2 In DirectCast(activity, CompositeActivity).Activities
                        queue.Enqueue(activity2)
                    Next
                End If
                If ((activity.Site Is Nothing) AndAlso Not IdentifierCreationService.IsPreBuiltActivity(activity)) Then
                    list.Add(activity)
                End If
            Loop
            Dim rootActivity As CompositeActivity = [TryCast](Helpers.GetRootActivity(parentActivity),CompositeActivity)
            Dim dictionary As New StringDictionary
            Dim rootActivityType As Type = Me.GetRootActivityType(Me.serviceProvider)
            If (Not rootActivity Is Nothing) Then
                Dim str As String
                For Each str In Helpers.GetIdentifiersInCompositeActivity(rootActivity)
                    dictionary.Item(str) = str
                Next
            End If
            If (Not rootActivityType Is Nothing) Then
                Dim info As MemberInfo
                For Each info In rootActivityType.GetMembers((BindingFlags.NonPublic Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance))))
                    Dim c As Type = Nothing
                    If TypeOf info Is FieldInfo Then
                        c = DirectCast(info, FieldInfo).FieldType
                    End If
                    If ((c Is Nothing) OrElse Not GetType(Activity).IsAssignableFrom(c)) Then
                        dictionary.Item(info.Name) = info.Name
                    End If
                Next
            End If
            Dim activity4 As Activity
            For Each activity4 In list
                Dim num As Integer = 0
                Dim baseIdentifier As String = Helpers.GetBaseIdentifier(activity4)
                Dim key As String = Nothing
                If (String.IsNullOrEmpty(activity4.Name) OrElse String.Equals(activity4.Name, activity4.GetType.Name, StringComparison.Ordinal)) Then
                    key = String.Format(CultureInfo.InvariantCulture, "{0}{1}", New Object() { baseIdentifier, ++num })
                Else
                    key = activity4.Name
                End If
                Do While dictionary.ContainsKey(key)
                    key = String.Format(CultureInfo.InvariantCulture, "{0}{1}", New Object() { baseIdentifier, ++num })
                    If (Not Me.Provider Is Nothing) Then
                        key = Me.Provider.CreateValidIdentifier(key)
                    End If
                Loop
                dictionary.Item(key) = key
                activity4.Name = key
            Next
        End Sub

        Private Sub System.Workflow.ComponentModel.Design.IIdentifierCreationService.ValidateIdentifier(ByVal activity As Activity, ByVal identifier As String) Implements IIdentifierCreationService.ValidateIdentifier
            If (identifier Is Nothing) Then
                Throw New ArgumentNullException("identifier")
            End If
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            If Not activity.Name.ToLowerInvariant.Equals(identifier.ToLowerInvariant) Then
                If (Not Me.Provider Is Nothing) Then
                    Dim supportedLanguage As SupportedLanguages = CompilerHelpers.GetSupportedLanguage(Me.serviceProvider)
                    If ((((supportedLanguage = SupportedLanguages.CSharp) AndAlso identifier.StartsWith("@", StringComparison.Ordinal)) OrElse (((supportedLanguage = SupportedLanguages.VB) AndAlso identifier.StartsWith("[", StringComparison.Ordinal)) AndAlso identifier.EndsWith("]", StringComparison.Ordinal))) OrElse Not Me.Provider.IsValidIdentifier(identifier)) Then
                        Throw New Exception(SR.GetString("Error_InvalidLanguageIdentifier", New Object() { identifier }))
                    End If
                End If
                Dim dictionary As New StringDictionary
                Dim rootActivity As CompositeActivity = [TryCast](Helpers.GetRootActivity(activity),CompositeActivity)
                If (Not rootActivity Is Nothing) Then
                    Dim str As String
                    For Each str In Helpers.GetIdentifiersInCompositeActivity(rootActivity)
                        dictionary.Item(str) = str
                    Next
                End If
                Dim rootActivityType As Type = Me.GetRootActivityType(Me.serviceProvider)
                If (Not rootActivityType Is Nothing) Then
                    Dim info As MemberInfo
                    For Each info In rootActivityType.GetMembers((BindingFlags.NonPublic Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance))))
                        Dim c As Type = Nothing
                        If TypeOf info Is FieldInfo Then
                            c = DirectCast(info, FieldInfo).FieldType
                        End If
                        If ((c Is Nothing) OrElse Not GetType(Activity).IsAssignableFrom(c)) Then
                            dictionary.Item(info.Name) = info.Name
                        End If
                    Next
                End If
                If dictionary.ContainsKey(identifier) Then
                    Throw New ArgumentException(SR.GetString("DuplicateActivityIdentifier", New Object() { identifier }))
                End If
            End If
        End Sub


        ' Properties
        Friend ReadOnly Property Provider As CodeDomProvider
            Get
                If (Me.provider Is Nothing) Then
                    If (CompilerHelpers.GetSupportedLanguage(Me.serviceProvider) = SupportedLanguages.CSharp) Then
                        Me.provider = CompilerHelpers.CreateCodeProviderInstance(GetType(CSharpCodeProvider))
                    Else
                        Me.provider = CompilerHelpers.CreateCodeProviderInstance(GetType(VBCodeProvider))
                    End If
                End If
                Return Me.provider
            End Get
        End Property


        ' Fields
        Private loader As WorkflowDesignerLoader
        Private provider As CodeDomProvider
        Private serviceProvider As IServiceProvider
    End Class
End Namespace

